package sonic.game.character;

import sonic.game.Game;
import sonic.game.animation.Animation;
import sonic.game.tile.Tile;
import sonic.game.util.Vector2D;

/**
 * 
 * Badnik class
 * @author RGreenlees
 * 
 * The base class for all AI enemies in the game. Contains a new aiUpdate method which handles decision making.
 * Also contains logic for firing projectiles at the player.
 *
 */

public class Badnik extends GameCharacter {
	
	// 0 = stationary, -1 = move left, 1 = move right
	protected int desiredDirection = 0;
	// Sound played when killed
	private String deathSound = "sounds/Badnik_death.wav";
	// How often this enemy can shoot at the player
	protected float fireRate = 0.0f;
	// Used to check how long it has been since the enemy last fired
	protected float fireTimer = 0.0f;
	// Having decided to shoot, how long it takes for the projectile to be launched
	protected float timeToFire = 0.0f;
	// Used to check how long the projectile has been charging up for
	protected float timeTakenToFire = 0.0f;
	// If true, the enemy will stop moving and play its shooting animation
	protected boolean bPendingFire = false;
	
	public Badnik(Vector2D startLoc)
	{
		super(startLoc);
		collisionType = eCollisionType.CT_TOUCHALL;
		accelRate = 6.0f;
	}
	
	
	/** Spawns the puff of smoke, plays the death sound and removes the enemy from the game */
	public void die()
	{
		createEffect(getCentre().x, getCentre().y, new Animation(0.25f, false, "Effects/Badnik_death_1.png", "Effects/Badnik_death_2.png", "Effects/Badnik_death_3.png", "Effects/Badnik_death_4.png"));
		playSound(deathSound);
		destroy();
	}
	
	/** Override to call an AI update alongside the regular update */
	public void update(double deltaTime)
	{		
		super.update(deltaTime);
		aiUpdate(deltaTime);
	}
	
	/** Simple AI. Will accelerate in the desired direction, changing if it hits a wall or reaches a ledge */
	public void aiUpdate(double deltaTime)
	{
		Vector2D endTraceRight, endTraceLeft;
		
		endTraceRight = new Vector2D(tileCorners[2].x, tileCorners[2].y + 10.0f);
		endTraceLeft = new Vector2D(tileCorners[3].x, tileCorners[3].y + 10.0f);
		
		if (desiredDirection == 0 && !bPendingFire)
		{
			desiredDirection = 1;
		}
		
		// Accelerate left or right
		if (desiredDirection == 1)
		{
			if (velocity.x < maxGroundSpeed)
			{
				velocity.x += 120*accelRate*Game.deltaTime;
			}
		}
		else if (desiredDirection == -1)
		{
			if (velocity.x > -maxGroundSpeed)
			{
				velocity.x -= 120*accelRate*Game.deltaTime;
			}
		}
		else
		{
			velocity.x = 0;
		}
		
		// If the enemy is moving on the floor and reaches a ledge, turn around
		if (physicsType == ePhysicsType.PHYS_WALKING)
		{
			// If moving right and the right trace hits empty space, then we're on a ledge
			if (fastTrace(tileCorners[2], endTraceRight, false) && desiredDirection == 1)
			{
				desiredDirection = -1;
			}
			else if (fastTrace(tileCorners[3], endTraceLeft, false) && desiredDirection == -1)
			{
				desiredDirection = 1;
			}
		}
		
		// If a fire rate has been specified and it's not already firing, then run the fire timer
		if (fireRate > 0 && !bPendingFire)
		{
			fireTimer += deltaTime;
			if (fireTimer > fireRate)
			{
				beginFire();
				fireTimer = 0.0f;
			}
		}
		
		// If the AI is taking a shot at the player, start the winding-up timer
		if (bPendingFire)
		{
			timeTakenToFire += deltaTime;
			// Finished winding-up timer, launch a projectile!
			if (timeTakenToFire > timeToFire)
			{
				shootAt(Game.player);
				timeTakenToFire = 0.0f;
				endFire();
			}
		}
		
		updateAnims();
	}
	
	public void shootAt(Tile target)
	{
	
	}
	
	// Start the firing animation. Stop moving while shooting
	public void beginFire()
	{
		bPendingFire = true;
		desiredDirection = 0;
		velocity.x = 0.0f;
		velocity.y = 0.0f;
	}
	
	public void endFire()
	{
		bPendingFire = false;
	}
	
	public void hitWall(Tile a)
	{
		super.hitWall(a);
		desiredDirection = -desiredDirection;
	}
	
	public void updateAnims()
	{
		if (Math.abs(velocity.x) > 12.0f)
		{
			bFaceLeft = (velocity.x < 0);
			currentAnimationSet.setCurrentAnimation("moveAnim");
		}
		else if (bPendingFire)
		{
			currentAnimationSet.setCurrentAnimation("shootAnim");
		}
		currentAnimationSet.update(Game.deltaTime);
	}

}
